﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Baidu.Aip;
using System.IO;
using System.Drawing.Imaging;
using System.Diagnostics;
using Newtonsoft.Json;
using System.Net;
using Newtonsoft.Json;

namespace LJDPlus
{
    public partial class Form1 : Form
    {
        // 设置APPID/AK/SK
        string APP_ID = "14130411";
        string API_KEY = "fAjA32Rpb1VbbHtx7bG9qD7E";
        string SECRET_KEY = "oZP9TTUPsK722jfrlfPhoa3Vsbr46qdU";

        Baidu.Aip.Ocr.Ocr client;

        string connDevice = string.Empty;

        public Form1()
        {
            client = new Baidu.Aip.Ocr.Ocr(API_KEY, SECRET_KEY);
            client.Timeout = 6000;  // 修改超时时间
            
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
           
        }

        public string GeneralBasic(Image image)
        {
            // 调用通用文字识别, 图片参数为本地图片，可能会抛出网络等异常，请使用try/catch捕获
            try
            {
                var result = client.GeneralBasic(ImageToBytes(image));

                return result.ToString();
            }
            catch (Exception e)
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// Convert Image to Byte[]
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public static byte[] ImageToBytes(Image image)
        {
            ImageFormat format = image.RawFormat;
            using (MemoryStream ms = new MemoryStream())
            {
                if (format.Equals(ImageFormat.Jpeg))
                {
                    image.Save(ms, ImageFormat.Jpeg);
                }
                else if (format.Equals(ImageFormat.Png))
                {
                    image.Save(ms, ImageFormat.Png);
                }
                else if (format.Equals(ImageFormat.Bmp))
                {
                    image.Save(ms, ImageFormat.Bmp);
                }
                else if (format.Equals(ImageFormat.Gif))
                {
                    image.Save(ms, ImageFormat.Gif);
                }
                else if (format.Equals(ImageFormat.Icon))
                {
                    image.Save(ms, ImageFormat.Icon);
                }
                else
                {
                    image.Save(ms, ImageFormat.Png);
                }

                byte[] buffer = new byte[ms.Length];
                //Image.Save()会改变MemoryStream的Position，需要重新Seek到Begin
                ms.Seek(0, SeekOrigin.Begin);
                ms.Read(buffer, 0, buffer.Length);
                return buffer;
            }
        }

        //private void button2_Click(object sender, EventArgs e)
        //{
        //    //string strImagePath = "t2.png";
        //    //this.pictureBox1.ImageLocation = strImagePath;
        //    //pictureBox1.Refresh();

        //    using (Graphics g = Graphics.FromImage(pictureBox1.Image))
        //    {
        //        Bitmap m = new Bitmap(pictureBox1.Image);
        //        Color color = m.GetPixel(int.Parse(this.textBox1.Text), int.Parse(this.textBox2.Text));
        //        this.textBox1.BackColor = color;

        //        int cr = Convert.ToInt32(color.R);
        //        int cb = Convert.ToInt32(color.B);
        //        int cg = Convert.ToInt32(color.G);

        //        //this.label1.Text = string.Format("R:{0},G:{1},B:{2}",cr,cg,cb);

        //        //Graphics g = pictureBox1.CreateGraphics();
        //        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

        //        Brush bush = new SolidBrush(Color.Red);//填充的颜色

        //        g.FillEllipse(bush, int.Parse(this.textBox1.Text), int.Parse(this.textBox2.Text), 10, 10);//画填充椭圆的方法，x坐标、y坐标、宽、高，如果是100，则半径为50

        //        //g.Clear(this.BackColor);

        //        pictureBox1.Refresh();
        //    }
        //}

        private void button3_Click(object sender, EventArgs e)
        {
            if (this.pictureBox1.Image != null)
            {
                int intQw = 0, intQh = 0, intQb = 0;

                int w = pictureBox1.Image.Width;
                int h = pictureBox1.Image.Height;

                Bitmap m = new Bitmap(pictureBox1.Image);
                for (int i = w - 1; i > 0; i--)
                {
                    for (int j = h - 1; j > 0; j--)
                    {
                        Color color = m.GetPixel(i, j);

                        int cr = Convert.ToInt32(color.R);
                        int cb = Convert.ToInt32(color.B);
                        int cg = Convert.ToInt32(color.G);

                        //模糊判断颜色值
                        if ((cr > 240 && cr < 255) &&
                            (cg > 20 && cg < 100) &&
                            (cb > 20 && cb < 100))
                        {
                            //this.textBox1.BackColor = color;

                            //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                            //Brush bush = new SolidBrush(Color.Black);//填充的颜色

                            //g.FillEllipse(bush, i, j, 3, 3);//画填充椭圆的方法，x坐标、y坐标、宽、高，如果是100，则半径为50

                            //intCount++;
                            intQw = i;
                            intQh = j;

                            i = 0;
                            break;
                        }
                    }
                }

                //往上找到边界位置
                for (int j = intQh; j > 0; j--)
                {
                    Color color = m.GetPixel(intQw, j);

                    int cr = Convert.ToInt32(color.R);
                    int cb = Convert.ToInt32(color.B);
                    int cg = Convert.ToInt32(color.G);

                    //模糊判断颜色值
                    if ((cr > 230 && cr < 250) &&
                        (cg > 220 && cg < 240) &&
                        (cb > 240 && cb < 256))
                    {
                        intQb = j;
                        break;
                    }
                }


                using (Graphics g = Graphics.FromImage(pictureBox1.Image))
                {
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                    g.DrawRectangle(new Pen(Color.Red, 1), 180, intQb, w - 1, intQh - intQb + 30);

                    Bitmap bmpImage = new Bitmap(pictureBox1.Image);
                    Rectangle cropArea = new Rectangle();

                    cropArea.X = 0;
                    cropArea.Y = intQb;
                    cropArea.Width = w - 1;
                    cropArea.Height = intQh - intQb + 30;

                    Bitmap bmpCrop = bmpImage.Clone(cropArea, bmpImage.PixelFormat);

                    string result = GeneralBasic(bmpCrop);

                    OCRResult oOCRResult = JsonConvert.DeserializeObject<OCRResult>(result);
                    if (oOCRResult != null)
                    {
                        List<lstword> lw = oOCRResult.words_result;
                        if (lw.Count > 0)
                        {
                            if (lw.Count > 3)
                                this.textBox3.Text = lw[lw.Count - 3].words + lw[lw.Count - 2].words;
                            else if (lw.Count == 3)
                                this.textBox3.Text = lw[0].words + lw[1].words;
                            else if (lw.Count == 2)
                                this.textBox3.Text = lw[0].words;
                        }
                    }

                }

                pictureBox1.Refresh();
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(this.cmbDevices.Text))
            {
                MessageBox.Show("请选择连接的设备。");
                return;
            }

            connDevice = string.Format(" -s {0} ", this.cmbDevices.Text);

            //string result = GetProcessResult(" devices");

            //if (!string.IsNullOrEmpty(result) && !string.IsNullOrEmpty(result.ToLower().Replace("list of devices attached", string.Empty)))
            //{
            //    bool conneted = false;

            //    //按行拆分
            //    string[] aryResult = result.Split('\n');

            //    for (int i = 0 ; i < aryResult.Length; i++)
            //    {
            //        if(aryResult[i].ToLower().Contains("device"))
            //        {
            //            conneted = true;
            //        }
            //    }

            //    if(!conneted)
            //    {
            //        this.textBox3.Text = result + "未能连接上设备，请检查adb驱动。";
            //        return;
            //    }

                //获取设备分辨率
                string wm = GetProcessResult(connDevice + " shell wm size");
                this.textBox3.Text = wm;

                wm = wm.ToLower().Replace("physical size:", string.Empty);
                int DevicesWidth = Convert.ToInt32(wm.Split('x')[0]);
                int DevicesHeight = Convert.ToInt32(wm.Split('x')[1]);

                //在缩小图片上移动鼠标时将鼠标坐标换算成原图片大小上的坐标
                //公式：缩小图片鼠标高度 × 比例 = 原图片坐标高度

                //计算缩小图片和原图片的比例
                double bili = (double)DevicesHeight / (double)DevicesWidth;
                //高度不变，宽度适应
                this.pictureBox1.Width = Convert.ToInt32((double)this.pictureBox1.Height / bili);
            //}
        }

        private string GetProcessResult(string Arguments)
        {
            
            ProcessStartInfo startInfo = new ProcessStartInfo();

            startInfo.FileName = @"C:\Program Files (x86)\ClockworkMod\Universal Adb Driver\adb.exe";

            startInfo.Arguments = Arguments;

            startInfo.UseShellExecute = false;

            startInfo.RedirectStandardInput = true;

            startInfo.RedirectStandardOutput = true;

            startInfo.RedirectStandardError = true;

            startInfo.CreateNoWindow = true;

            startInfo.StandardOutputEncoding = Encoding.GetEncoding("GBK");

            Process p = new Process();
            p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            p.StartInfo = startInfo;
            p.OutputDataReceived += p_OutputDataReceived;
            p.Exited += p_Exited;
            p.Start();

            string outstr = p.StandardOutput.ReadToEnd();

            p.WaitForExit();

            return outstr;
        }

        void p_Exited(object sender, EventArgs e)
        {
            Console.Write("exit");
        }

        void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            Console.Write(e.Data);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            this.pictureBox1.Image = null; 
            File.Delete("screenshot.png");
            File.Delete("d.png");

            this.textBox3.Text = GetProcessResult("  shell screencap -p /sdcard/screenshot.png ; ");
            this.textBox3.Text = GetProcessResult("  pull /sdcard/screenshot.png screenshot.png ");

            CompressImage("screenshot.png", "d.png", 100, 1067);

            string strImagePath = "d.png";
            this.pictureBox1.ImageLocation = strImagePath;

        }

        #region 无损压缩图片
        /// <summary>
        /// 无损压缩图片
        /// </summary>
        /// <param name="sFile">原图片地址</param>
        /// <param name="dFile">压缩后保存图片地址</param>
        /// <param name="flag">压缩质量（数字越小压缩率越高）1-100</param>
        /// <param name="size">压缩后图片的最大大小</param>
        /// <param name="sfsc">是否是第一次调用</param>
        /// <returns></returns>
        public static bool CompressImage(string sFile, string dFile, int flag = 90, int size = 300, bool sfsc = true)
        {
            System.Drawing.Image iSource = System.Drawing.Image.FromFile(sFile);
            ImageFormat tFormat = iSource.RawFormat;
            //如果是第一次调用，原始图像的大小小于要压缩的大小，则直接复制文件，并且返回true
            FileInfo firstFileInfo = new FileInfo(sFile);
            if (sfsc == true && firstFileInfo.Length < size * 1024)
            {
                firstFileInfo.CopyTo(dFile,true);
                return true;
            }

            int dHeight = iSource.Height / 2;
            int dWidth = iSource.Width / 2;
            int sW = 0, sH = 0;
            //按比例缩放
            Size tem_size = new Size(iSource.Width, iSource.Height);
            if (tem_size.Width > dHeight || tem_size.Width > dWidth)
            {
                if ((tem_size.Width * dHeight) > (tem_size.Width * dWidth))
                {
                    sW = dWidth;
                    sH = (dWidth * tem_size.Height) / tem_size.Width;
                }
                else
                {
                    sH = dHeight;
                    sW = (tem_size.Width * dHeight) / tem_size.Height;
                }
            }
            else
            {
                sW = tem_size.Width;
                sH = tem_size.Height;
            }

            Bitmap ob = new Bitmap(dWidth, dHeight);
            Graphics g = Graphics.FromImage(ob);

            g.Clear(Color.WhiteSmoke);
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);

            g.Dispose();

            //以下代码为保存图片时，设置压缩质量
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;

            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo jpegICIinfo = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                if (jpegICIinfo != null)
                {
                    ob.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径
                    FileInfo fi = new FileInfo(dFile);
                    if (fi.Length > 1024 * size)
                    {
                        flag = flag - 10;
                        CompressImage(sFile, dFile, flag, size, false);
                    }
                }
                else
                {
                    ob.Save(dFile, tFormat);
                }
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                iSource.Dispose();
                ob.Dispose();
            }
        }
        #endregion

        private void button6_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            this.webBrowser1.Navigate(string.Format("https://search.jd.com/Search?keyword={0}&enc=utf-8&suggest=1.his.0.0&wq=",
                System.Web.HttpUtility.UrlEncode(this.textBox3.Text , System.Text.Encoding.UTF8)));
        }

        private void GetScreenShot()
        {
            this.pictureBox1.Image = null;
            File.Delete("screenshot.png");
            File.Delete("d.png");

            this.textBox3.Text = GetProcessResult("  shell screencap -p /sdcard/screenshot.png ; ");
            this.textBox3.Text = GetProcessResult("  pull /sdcard/screenshot.png screenshot.png ");

            this.pictureBox1.ImageLocation = "screenshot.png";

        }

        private void TAP(int x ,int y)
        {
            this.textBox3.Text = GetProcessResult(string.Format(" shell input tap {0} {1}", x, y));
        }

        private void Swipe(int x1, int y1, int x2, int y2)
        {
            this.textBox3.Text = GetProcessResult(string.Format(" shell input swipe {0} {1} {2} {3}", x1, y1,x2,y2));
        }

        //记录鼠标按下坐标，当按下和弹上的坐标一致时，认定为一次TAP点击，否则为滑动
        int mx = 0;
        int my = 0;

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            mx = e.X;
            my = e.Y;

            //记录动作
            
        }

        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            //TAP
            if (mx == e.X && my == e.Y)
            {
                TAP(reverseW(mx), reverseH(my));

                GetScreenShot();

                if (this.timer1.Enabled)
                    dic.Add(dbTime , new Position("tap" , mx,my,mx,my));
            }
            else
            {
                Swipe(reverseW(mx), reverseH(my), reverseW(e.X), reverseH(e.Y));

                GetScreenShot();

                if (this.timer1.Enabled)
                    dic.Add(dbTime, new Position("swipe" , mx, my, e.X, e.Y));
            }
        }

        private int reverseW(int x)
        {
            if (this.pictureBox1.Image == null) return x;

            return Convert.ToInt32(x * ((double)this.pictureBox1.Image.Width / (double)this.pictureBox1.Width));
        }

        private int reverseH(int y)
        {
            if (this.pictureBox1.Image == null) return y;

            return Convert.ToInt32(y * ((double)this.pictureBox1.Image.Height / (double)this.pictureBox1.Height));
        }

        Dictionary<double, Position> dic = new Dictionary<double, Position>();
        ArrayList aryList = new ArrayList();
        double dbTime = 0;

        private void timer1_Tick(object sender, EventArgs e)
        {
            dbTime++;
        }

        private void button7_Click(object sender, EventArgs e)
        {
            if (this.timer1.Enabled)
            {
                this.button7.Text = "录制动作";
                this.timer1.Stop();
            }
            else
            {
                dbTime = 0;
                dic.Clear();
                aryList.Clear();
                this.button7.Text = "停止录制";
                this.timer1.Start();

            }
        }

        private void button8_Click(object sender, EventArgs e)
        {
            dbTime = 0;
            this.timer2.Start();

            
        }

        int tmp = 0; //计算动作是否完成
        private void timer2_Tick(object sender, EventArgs e)
        {
            dbTime++;

            if (dic.Keys.Contains(dbTime))
            {
                Position p = dic[dbTime];
                
                switch (p.A.ToLower())
                {
                    case "tap":
                        TAP(reverseW(p.X1), reverseH(p.Y1));
                        break;
                    case "swipe":
                        Swipe(reverseW(p.X1), reverseH(p.Y1), reverseW(p.X2), reverseH(p.Y2));
                        break;
                    case "menu":
                        btnMenu_Click(this.btnMenu, null);
                        break;
                    case "task":
                        btnTask_Click(this.btnTask, null);
                        break;
                    case "back":
                        btnBack_Click(this.btnBack, null);
                        break;

                }

                this.textBox3.Text = string.Format("执行动作：{0}({1},{2},{3},{4})" , p.A, p.X1 , p.Y1 , p.X2 , p.Y2);

                tmp++;
            }

            //动作完成自动终止
            if (tmp >= dic.Keys.Count)
            {
                this.timer2.Stop();
            }
        }

        private void button9_Click(object sender, EventArgs e)
        {
            string jsonAction = JsonConvert.SerializeObject(dic);

            if (File.Exists("Action.txt"))
                File.Delete("Action.txt");

            StreamWriter sw = File.CreateText("Action.txt");
            sw.Write(jsonAction);
            sw.Flush();
            sw.Close();

        }

        private void button10_Click(object sender, EventArgs e)
        {
            dic.Clear();
            aryList.Clear();

            JsonSerializer serializer = new JsonSerializer();
            StreamReader sr = new StreamReader("Action.txt");
            object o = serializer.Deserialize(new JsonTextReader(sr), typeof(Dictionary<double, Position>));
            dic = o as Dictionary<double, Position>;

        }

        private void btnMenu_Click(object sender, EventArgs e)
        {
            GetProcessResult(" shell input keyevent 82");   //82菜单键

            //检测是否在录制动作
            if (this.timer1.Enabled)
            {
                dic.Add(dbTime, new Position("menu", 0, 0, 0, 0));
            }
        }

        private void btnTask_Click(object sender, EventArgs e)
        {
            GetProcessResult(" shell input keyevent 3");   //3HOME 键

            //检测是否在录制动作
            if (this.timer1.Enabled)
            {
                dic.Add(dbTime, new Position("home", 0, 0, 0, 0));
            }
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            GetProcessResult(" shell input keyevent 4");   //4 返回键

            //检测是否在录制动作
            if (this.timer1.Enabled)
            {
                dic.Add(dbTime, new Position("back", 0, 0, 0, 0));
            }
        }

        private void button11_Click(object sender, EventArgs e)
        {

        }

        private void btnGetDevices_Click(object sender, EventArgs e)
        {
            this.cmbDevices.Items.Clear();

            string result = GetProcessResult(" devices");

            result = result.ToLower().Replace("list of devices attached", string.Empty);
            
            //按行拆分
            string[] aryResult = result.Split('\n');

            for (int i = 0; i < aryResult.Length; i++)
            {
                aryResult[i] = aryResult[i].Replace("\r", "");

                string[] t = aryResult[i].Split('\t');
                if(!string.IsNullOrEmpty(t[0]))
                    this.cmbDevices.Items.Add(t[0]);

            }
            
        }
    }

    #region 记录动作和位置

    /// <summary> 
    /// 记录动作和位置
    /// </summary>
    public class Position
    {
        public Position(string A , int X1, int Y1, int X2, int Y2)
        {
            this.A = A;
            this.X1 = X1;
            this.Y1 = Y1;
            this.X2 = X2;
            this.Y2 = Y2;
        }

        public string A
        {
            get;
            set;
        }

        public int X1
        {
            get;
            set;
        }

        public int Y1
        {
            get;
            set;
        }

        public int X2
        {
            get;
            set;
        }

        public int Y2
        {
            get;
            set;
        }
    }
    #endregion
}
